package com.neu.gulimall.config;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

@Configuration
public class MyRabbitMQConfig {

//    @Autowired
//    private RabbitTemplate rabbitTemplate;

    // 当发送的消息是一个对象时，序列化时以json的方式
    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }

//    /**
//     *  定制 rabbitTemplate
//     *  1、服务收到消息就会回调
//     *      *      1、spring.rabbitmq.publisher-confirms: true
//     *      *      2、设置确认回调
//     *      * 2、消息正确抵达队列就会进行回调
//     *      *      1、spring.rabbitmq.publisher-returns: true
//     *      *         spring.rabbitmq.template.mandatory: true
//     *      *      2、设置确认回调ReturnCallback
//     *      *
//     *      * 3、消费端确认(保证每个消息都被正确消费，此时才可以broker删除这个消息)
//     *          1、默认是自动确认的，只要消息接收到，客户端就会自动确认，服务端就会移除这个消息
//     *              问题：
//     *                  我们受到很多消息，自动回复给服务器ack，只有一个消息处理成功，然后宕机了，此时就会发生消息丢失，没有处理的消息全没了。
//     *                  使用手动确认、只要我们没有明确 告诉mq，消息被签收了，没有ack，消息就一直是unacked状态，即使消费者宕机了，消息页不会丢失，会重新变为ready状态
//     *                  下一次消费者重新启动，就会重新发给他
//     *          2、如果签收
//     *              channel.basicAck(); 签收
//     *              channel.basicNack(); 拒签
//     */
//    @PostConstruct  // MyRabbitMQConfig对象创建以后，再来执行这个方法
//    public void initRabbitTemplate(){
//        // 设置确认回调
//        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
//
//            /**
//             * 1、做好消息确认机制（publisher、consumer【手动ack】）
//             * 2、每一个发送的消息都在数据库中做好记录，定期将失败的消息再次发送一遍
//             *
//             * 只要服务器成功收到就会执行该回调
//             * @param correlationData  当前消息的唯一关联数据（这个是消息的唯一id）
//             * @param b  消息是否成功收到 只要消息成功发送给到broker（消息代理服务器）就是true
//             * @param s  失败的原因
//             */
//            @Override
//            public void confirm(CorrelationData correlationData, boolean b, String s) {
//                // 服务器收到了
//            }
//        });
//
//        // 设置消息抵达队列的确认回调
//        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
//            /**
//             *  只要消息没有投递给指定的队列，就触发这个失败的回调
//             * @param message 投递失败的消息的详细内容
//             * @param i 回复的状态码
//             * @param s 回复的文本内容
//             * @param s1 当时这个消息发送给哪个交换机
//             * @param s2 当时这个消息用哪个路由键
//             */
//            @Override
//            public void returnedMessage(Message message, int i, String s, String s1, String s2) {
//
//            }
//        });
//    }

}
